package com.example.aopproject;

import android.util.Log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

/**
 * 类名：BehaviorAspect<br></br>
 * 主要功能：相当于切面<br></br>
 * 创建日期：09/09/2017  10:09
 */
@Aspect
public class BehaviorAspect {
    private static final String TAG = "AOP";
    private static final String POINTCUT_METHOD = "execution(@com.example.aopproject.BehaviorAnn * *(..))";
    private static final String POINTCUT_START_METHOD = "execution(@com.example.aopproject.BehaviorAnn * sayHello(..))";

    /**
     * Create a log message.
     *
     * @param methodName     A string with the method name.
     * @param methodDuration Duration of the method in milliseconds.
     * @return A string representing message.
     */
    private static String buildLogMessage(String methodName, long methodDuration) {
        StringBuilder message = new StringBuilder();
        message.append("Kotlin --> ");
        message.append(methodName);
        message.append(" --> ");
        message.append("[");
        message.append(methodDuration);
        message.append("ms");
        message.append("]");

        return message.toString();
    }

    @Before(POINTCUT_START_METHOD)
    public void before(JoinPoint point) {
        Log.d(TAG, point.getKind());
        Log.d(TAG, "Before");
    }

    // gey cut point
    @Pointcut(POINTCUT_METHOD)
    public void annBehavior() {
        // empty
    }

    // handle advice
    @Around("annBehavior()")
    public Object dealPoint(ProceedingJoinPoint point)
            throws Throwable {
        // 方法执行前
        MethodSignature methodSignature = (MethodSignature) point.getSignature();// 获取方法签名
        BehaviorAnn behaviorTrace = methodSignature.getMethod().getAnnotation(BehaviorAnn.class);// 获取注解(不是RUNTIME获取不到的)
        int level = behaviorTrace.level();// 调用注解的方法
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getName();

        // 方法执行时
        final TimeWatcher stopWatch = new TimeWatcher();
        stopWatch.start();
//        // 模拟权限管理
//        Log.d(TAG, "level:" + level);
        Object object = null;
//        if (level > 2) {
        try {
            object = point.proceed();
        } catch (Exception e) {
            e.printStackTrace();
        }
//        }
        stopWatch.stop();

        // 方法执行完成
        DebugLog.log(className, buildLogMessage(methodName, stopWatch.getTotalTimeMillis()));
        return object;
    }

    @AfterThrowing(value = POINTCUT_START_METHOD, throwing = "ex")
    public void afterThrowing(Throwable ex) {
        Log.d(TAG, "AfterThrowing:" + ex.getMessage());
    }

    @AfterReturning(value = POINTCUT_START_METHOD, returning = "result")
    public void afterReturning(JoinPoint point, Object result) {
        Log.d(TAG, ((String) result));
        Log.d(TAG, "AfterReturning");
    }

    @After(POINTCUT_START_METHOD)
    public void after(JoinPoint point) {
        Log.d(TAG, "After");
    }
}
